#include "amperimeter_acs71x.h"

// driver para ler o valor da corrente baseado no acs71x

typedef struct {
	uint sensitivity;
	uint resin, resdown;
	s32 offset;
}tAmp;

static tAmp sensors[ACS71X_N_SENSORS]; // vetor de tipos de modelos de sensores a ser gerenciados

// inicializa os parametros para calculos para o modelo de termistor especificado
// parametros:	tidx: Descrimina o sensor a ser gerencicado
//				sen: Valor da sensibilidade do sensor
// 					ACS de 5A, sensibilidade de 185mv/A
// 					ACS de 20A, sensibilidade de 100mv/A
// 					ACS de 30A, sensibilidade de 66mv/A
//				rin: Valor do resistor de entrada em ohms do circuito da interface do sensor. Valor 0 não usa
//				rdown: Valor do resistor pulldown em ohms do circuito da interface do sensor. Valor 0 não usa
// 				rin e rdown é um divisor resistivo para que um ADC de 3.3V possa ler o módulo amperimento cujo a sua saída é de 0 a 5V.
void acx71x_Init(uint tidx, uint sen, uint rin, uint rdown) {
	if (tidx >= ACS71X_N_SENSORS) return;
	sensors[tidx].sensitivity = sen;
	sensors[tidx].resin = rin;
	sensors[tidx].resdown = rdown;
	sensors[tidx].offset = 0;
}

// Ajusta o deslocamento da reta da leitura dos sensores para obtermos a leitura de 0mA quando não há corrente
// parametros:	tidx: Descrimina o sensor a ser gerencicado
// 				value: Valor de deslocamento em miliamperes
void acx71x_SetOffSet(uint tidx, s32 value) {
	if (tidx >= ACS71X_N_SENSORS) return;
	sensors[tidx].offset = value;
}

// Lê deslocamento da reta da leitura dos sensores para obtermos a leitura de 0mA quando não há corrente
// parametros:	tidx: Descrimina o sensor a ser gerencicado
// retorna: com o valor de deslocamento em miliamperes
s32 acx71x_ReadOffSet(uint tidx) {
	if (tidx >= ACS71X_N_SENSORS) return 0;
	return sensors[tidx].offset;
}

// converte para amperagem o valor lido na ponta de prova
//	tidx: Indice do sensor a ser lido: 0=sensor 1, 1=sensor2 e assim sucessivamente
//	adc: Valor adc lido do respectivo sensor
// retorna em microamperes

// para mais detalhes veja D:\meus_conhecimentos\_devices_misc__\sensor_tensão
// retorna com o valor da tensão lida no circuito correspondente ao ADC
// parametros:	tidx: Descrimina o sensor a ser gerencicado
//				adc: Valor lido do ADC
static double acx71x_ValueVoltage(uint tidx, uint adc) {
	double voltage = (adc*ACS71X_AVCC)/(_BV(ACS71X_BIT_RESOLUTION)-1);

	// se o módulo amperimetro contém um divisor de tensão para um ADC de 3v3 poder ler, vamos converter a tensão
	if ( (sensors[tidx].resin) && (sensors[tidx].resdown) )
		voltage = ((((double)sensors[tidx].resin+(double)sensors[tidx].resdown)*voltage)/sensors[tidx].resdown);

	return voltage;
}

// retorna o valor em miliamperes
// parametros:	tidx: Descrimina o sensor a ser gerencicado
//				adc: Valor lido do ADC
s32 acx71x_ConvertToAmperage(uint tidx, uint adc) {
	if (tidx >= ACS71X_N_SENSORS) return 0;

	// Ler a tensão do módulo amperimetro referente a leitura da amperagem
	double voltage = acx71x_ValueVoltage(tidx, adc);
  	double zeroCurrentVcc = ((double)5.0)/2.0;
  	double diff = voltage - zeroCurrentVcc;
  	double current  = diff / (double)(sensors[tidx].sensitivity/1000.0);

  	return (s32)(current*1000) - sensors[tidx].offset;
}
